package com.ideaaedi.springcloud.jd.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ideaaedi.springcloud.jd.commonds.constant.BaseConstant;
import com.ideaaedi.springcloud.jd.commonds.entity.BaseCodeMsgEnum;
import com.ideaaedi.springcloud.jd.commonds.entity.PageInfo;
import com.ideaaedi.springcloud.jd.commonds.event.user.SysPostDeletedEvent;
import com.ideaaedi.springcloud.jd.commonds.entity.user.po.SysPostPO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.req.SysPostAddReqVO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.req.SysPostListReqVO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.req.SysPostUpdateReqVO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.resp.SysPostDetailRespVO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.resp.SysPostListRespVO;
import com.ideaaedi.springcloud.jd.commonds.exception.BaseException;
import com.ideaaedi.springcloud.jd.commonspring.mybatisplus.ServiceImplExt;
import com.ideaaedi.springcloud.jd.commonspring.util.JdContextUtil;
import com.ideaaedi.springcloud.jd.commonspring.validator.ValidId;
import com.ideaaedi.springcloud.jd.commonspring.validator.ValidTenant;
import com.ideaaedi.springcloud.jd.user.mapper.SysPostMapper;
import com.ideaaedi.springcloud.jd.user.service.SysPostService;
import com.ideaaedi.springcloud.jd.user.support.UserCheckSupport;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 职位 服务实现类
 * </p>
 *
 * @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img
 * src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
 * @since 2021.0.1.A
 */
@Service
public class SysPostServiceImpl extends ServiceImplExt<SysPostMapper, SysPostPO> implements SysPostService {
    
    @Resource
    private UserCheckSupport userCheckSupport;
    
    @Override
    @ValidTenant
    @Transactional(rollbackFor = Exception.class)
    public SysPostDetailRespVO add(SysPostAddReqVO req) {
        String tenant = req.getTenant();
        if (StringUtils.isBlank(tenant)) {
            tenant = JdContextUtil.currUserTenantNonNull();
        }
        // 校验code是否被占用
        String code = req.getCode();
        if (code != null) {
            userCheckSupport.checkExistSamePostCode(tenant, code, null);
        }
        
        SysPostPO po = new SysPostPO();
        BeanUtils.copyProperties(req, po, BaseConstant.TENANT);
        if (StringUtils.isNotBlank(tenant)) {
            po.setTenant(tenant);
        }
        long id = IdWorker.getId();
        po.setId(id);
        save(po);
        return detail(id);
    }
    
    @Override
    @ValidId
    @Transactional(rollbackFor = Exception.class)
    public SysPostDetailRespVO delete(Long id) {
        Objects.requireNonNull(id, "id cannot be null.");
        SysPostPO po = getById(id);
        SysPostDetailRespVO resp = detail(po);
        removeById(id);
        // 发布事件
        applicationContext.publishEvent(new SysPostDeletedEvent(po));
        return resp;
    }
    
    @Override
    @ValidTenant
    @Transactional(rollbackFor = Exception.class)
    public SysPostDetailRespVO update(SysPostUpdateReqVO req) {
        String tenant = req.getTenant();
        Long id = req.getId();
        // 原来的po
        SysPostPO oldPo = getById(id);
        if (oldPo == null) {
            throw new BaseException("post id -> " + id, BaseCodeMsgEnum.DATA_NON_EXIST_OR_NON_DATA_PERMISSION);
        }
        if (StringUtils.isBlank(tenant)) {
            tenant = oldPo.getTenant();
        }
        
        // 校验code是否被占用
        String code = req.getCode();
        if (code != null) {
            userCheckSupport.checkExistSamePostCode(tenant, code, id);
        }
        
        SysPostPO po = new SysPostPO();
        BeanUtils.copyProperties(req, po, BaseConstant.TENANT);
        if (StringUtils.isNotBlank(tenant)) {
            po.setTenant(tenant);
        }
        updateById(po);
        return detail(po.getId());
    }
    
    @Override
    public SysPostDetailRespVO detail(Long id) {
        Objects.requireNonNull(id, "id cannot be null.");
        SysPostPO po = getById(id);
        if (po == null) {
            return null;
        }
        return detail(po);
    }
    
    @Override
    public PageInfo<SysPostListRespVO> list(SysPostListReqVO req) {
        String code = req.getCode();
        String name = req.getName();
        Integer grade = req.getGrade();
        Integer state = req.getState();
        int pageNum = req.getPageNum();
        int pageSize = req.getPageSize();
        
        // 分页查
        IPage<SysPostPO> pageInfo = new Page<>(pageNum, pageSize);
        IPage<SysPostPO> page = this.baseMapper.selectPage(pageInfo,
                new LambdaQueryWrapper<SysPostPO>()
                        .eq(grade != null, SysPostPO::getGrade, grade)
                        .eq(state != null, SysPostPO::getState, state)
                        .like(StringUtils.isNotBlank(name), SysPostPO::getName, name)
                        .like(StringUtils.isNotBlank(code), SysPostPO::getName, code)
                        .last("ORDER BY IFNULL(sort, " + Integer.MAX_VALUE + ") ASC, id DESC")
        );
        // 转换为resp模型
        List<SysPostPO> records = page.getRecords();
        List<SysPostListRespVO> list;
        if (CollectionUtils.isEmpty(records)) {
            list = Collections.emptyList();
        } else {
            list = records.stream().map(po -> {
                SysPostListRespVO resp = new SysPostListRespVO();
                BeanUtils.copyProperties(po, resp);
                return resp;
            }).collect(Collectors.toList());
        }
        return PageInfo.of(page.getTotal(), pageNum, pageSize, list);
    }
    
    @NotNull
    private static SysPostDetailRespVO detail(SysPostPO po) {
        SysPostDetailRespVO resp = new SysPostDetailRespVO();
        BeanUtils.copyProperties(po, resp);
        return resp;
    }
}
